#lang sicp
(define (accumulate combiner null-value term a next b)
  (define (iter res cur)
    (if (> cur b)
        res
        (iter (combiner res (term cur)) (next cur))))
  (iter null-value a))
(define (product term a next b)
  (accumulate * 1 term a next b))
(define (sum term a next b)
  (accumulate + 0 term a next b))
(define (factorial n)
  (product identity 1 inc n))
(define (get-pi up)
  (* 4
     (product (lambda (x)
                (/ (* x (+ 2 x))
                   (square (+ 1 x))))
              2.0
              (lambda (x) (+ 2 x))
              up)))
(define (square x) (* x x))
(define (sum-integers a b)
  (sum identity a inc b))

(define (filtered-accumulate combiner null-value term a next b filter?)
  (define (iter res cur)
    (cond ((> cur b) res)
          ((filter? cur)
           (iter (combiner res (term cur)) (next cur)))
          (else
           (iter res (next cur)))))
  (iter null-value a))

(define (sum-prime a b)
  (filtered-accumulate + 0 identity a inc b (lambda (x) (cond ((prime? x) (display x) (display " ") true)
                                                              (else false)))))

(define (prime? n)
  (= (smallest-divisor n) n))
(define (smallest-divisor n)
  (define (find a)
    (cond ((> (square a) n) n)
          ((= 0 (remainder n a)) a)
          (else (find (+ 1 a)))))
  (find 2))

(define (mutual-prime n)
  (filtered-accumulate * 1 identity 1 inc (- n 1)
                       (lambda (x)
                         (cond ((= (gcd x n) 1)
                                (display x)
                                (display " ")
                                true)
                               (else false)))))
